package ee.fj.http;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;


public class Server implements Runnable {
	private static final Logger logger = Logger.getLogger(Server.class.getName());
	private final ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
	private final ServerSocket server;
	private boolean isRunning = true;
	private BinderImpl binder;
	private final String serverName;

	public Server(InetAddress addr, int port, String serverName) throws UnknownHostException, IOException {
		server = new ServerSocket(port, 10, addr);
		this.serverName = serverName;
	}
	public Server(InetAddress addr, int port) throws UnknownHostException, IOException {
		this(addr, port, "FJ tiny server");
	}

	
	public synchronized Binder bind(ResponseHandler handler) {
		this.binder = new BinderImpl(handler, Request.DEFAULT_PATH);
		return this.binder;
	}

	@Override
	public void run() {
		while (isRunning) {
			try {
				Socket connected = server.accept();
				ServerHandler handler = new ServerHandler(serverName, connected, binder);
				service.execute(handler);
			} catch (SocketException e) {
				isRunning = false;
			} catch (Throwable e) {
				logger.log(Level.SEVERE, e.getMessage(), e);
			}
		}
		System.exit(0);
	}

	public void start() {
		service.execute(this);
	}
	public void stop() throws IOException, InterruptedException {
		if (isRunning) {
			isRunning = false;
			try {
				service.shutdown();
			} finally {
				server.close();
			}
		}
	}
}
